<template>
  <div :class="[chartClass, 'components-chart-box', props.bordered && 'bordered']" v-loading="loading"
    :style="{ height, width }">
    <div class='chart-container'>
      <h4 v-if="props.title" class="chart-title">{{ props.title }}</h4>
      <div class="chart" ref="chartRef">
      </div>
    </div>
    <div class="legend-box" v-if="colorChartData.length > 0 && legendExist">
      <ul class="legend-list" ref="scrollContent">
        <li v-for="(item, index) in colorChartData" :key="index" @mouseover="hoverSeries(item.name)"
          @mouseleave="hoverCancel(item.name)" @click="toggleSeries(item.name)">
          <span class="legend"
            :style="{ background: `linear-gradient(90deg, ${item.colorArr[0]}, ${item.colorArr[1]})` }"></span>
          <div class="value-box">
            <span>{{ item.name }}：</span>
            <span class="value">{{ item.value }}</span>
          </div>
        </li>
      </ul>
      <div v-if="showPage" class="op-box">
        <a-button type="link" :icon="h(CaretUpOutlined)" @click="scroll(-1)" :disabled="currentPage === 1"></a-button>
        {{ currentPage }}/{{ totalPages }}
        <a-button type="link" :icon="h(CaretDownOutlined)" @click="scroll(1)"
          :disabled="currentPage === totalPages"></a-button>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { onMounted, PropType, Ref, ref, watch, onUnmounted, h, nextTick } from 'vue'
import { useECharts } from '@/hooks/web/useECharts'
import { EChartsOption } from 'echarts'
import { getRandomColor, lightenColor } from '../common'
import { pieColorArr } from './data'
import { YData } from '@/api/common/model/chart'
import { CaretUpOutlined, CaretDownOutlined } from '@ant-design/icons-vue'
import '../style.scss'

const props = defineProps({
  width: {
    type: String as PropType<string>,
    default: '100%',
  },
  height: {
    type: String as PropType<string>,
    default: '100%',
  },
  loading: {
    type: Boolean,
    default: false,
  },
  bordered: {
    type: Boolean,
    default: true,
  },
  title: {
    type: String as PropType<string>,
    default: '',
  },
  chartData: {
    type: Array as PropType<YData[]>,
    default: () => [],
  },
  chartClass: {
    type: Object as PropType<string>,
  },
  legendExist: {
    type: Boolean,
    default: true,
  },
})

interface ColorData extends YData {
  colorArr: string[]
}

let resizeObserver: ResizeObserver | null = null
const chartRef = ref<HTMLDivElement | null>(null)
const scrollContent = ref<HTMLElement | null>(null)
const showPage = ref(false)
const itemHeight = 18
const colorChartData = ref<ColorData[]>([])
const chartWidth = ref(0)
const chartHeight = ref(0)
const itemsPerPage = ref(0) // 每页显示的图例数量
const totalPages = ref(0) // 总页数
const currentPage = ref(1) // 当前页码
const { setOptions, echarts, resize, getInstance } = useECharts(chartRef as Ref<HTMLDivElement>)

// 刻度
const bgGaugeR = 90
const gap = 0.5
// 外层圆
const bgBigPieR = [bgGaugeR - 15 - gap, bgGaugeR - 15]
// 数据圆
const pieR = [bgBigPieR[0] / 2, bgBigPieR[0] - 1]
// 内层圆
const bgSmallPieR = [pieR[0] - 2, pieR[0] - 1]
// 数据圆
const pieC = ['50%', '50%']

// 背景色
const bgLineColor = 'rgba(36,108,249,0.2)'

const pieBgOptions = [
  // 外环
  {
    type: 'pie',
    silent: true,
    radius: bgBigPieR.map(num => `${num}%`), //图表尺寸
    center: pieC,
    animation: false,
    emptyCircleStyle: {
      color: bgLineColor,
    },
  },
  // 内环
  {
    type: 'pie',
    silent: true,
    radius: bgSmallPieR.map(num => `${num}%`), //图表尺寸
    center: pieC,
    color: bgLineColor,
    animation: false,
    emptyCircleStyle: {
      color: bgLineColor,
    },
  },
  {
    type: 'gauge',
    splitNumber: 30, //刻度数量
    min: 0,
    max: 100,
    radius: `${bgGaugeR}%`, //图表尺寸
    center: pieC,
    startAngle: 0,
    endAngle: 360,
    axisLine: {
      lineStyle: {
        width: 1.5,
        shadowBlur: 0,
        color: [[1, bgLineColor]],
      },
    },
    axisTick: {
      show: true,
      lineStyle: {
        color: bgLineColor,
        width: 1,
      },
      length: '7%',
      distance: 2,
      splitNumber: 2,
    },
    splitLine: {
      show: false,
    },
    axisLabel: {
      show: false,
    },
    pointer: {
      show: false,
    },
    detail: {
      show: false,
    },
  },
]

const setChartColor = () => {
  if (!Array.isArray(props.chartData)) return
  colorChartData.value = props.chartData.map((item, index) => {
    let colorArr = pieColorArr?.[index]
    if (!colorArr) {
      const color1 = getRandomColor()
      const color2 = lightenColor(color1)
      colorArr = [color1, color2]
    }
    return ({
      ...item, colorArr
    })
  })
}

const getChartOptions = () => {
  const chartData = colorChartData.value
  const option = {
    backgroundColor: '#fff',
    tooltip: {
      trigger: 'item',
    },
    legend: {
      show: false,
      type: 'scroll',
      orient: 'vertical',

    },
    series: [
      // ...pieBgOptions,
      {
        type: 'pie',
        minAngle: 5, // 设置最小扇区角度
        // radius: pieR.map(num => `${num}%`),
        // center: pieC,
        radius: '50%',
        data: chartData,
        avoidLabelOverlap: true,
        itemStyle: {
          color: ({ data: { colorArr } }) => {
            return new echarts.graphic.LinearGradient(0, 0, 0, 1, [
              { offset: 0, color: colorArr[1] },
              { offset: 1, color: colorArr[0] },
            ])
          },
        },
        // labelLine: {
        //   show: true,
        //   showAbove: true,
        //   length: '7%',
        //   // length2: '8%',
        //   smooth: true,
        // },
        label: {
          formatter: function (params) {
            return `${params.name}: ${params.percent}%`; // 在 name 中带上 value
          },
          rich: {
            name: {
              fontSize: 12,
              color: '#333'
            },
            value: {
              fontSize: 12,
              color: '#666',
              padding: [0, 0, 0, 10] // 添加一些间距
            }
          }
        }
      }
    ],
  }
  return option as EChartsOption
}

onMounted(() => {
  resizeObserver = new ResizeObserver(() => {
    resize()
    getDomSize()
    calculatePagination()
  })
  if (chartRef.value) {
    resizeObserver.observe(chartRef.value as HTMLDivElement)
  }
})

onUnmounted(() => {
  if (resizeObserver && chartRef.value) {
    resizeObserver.unobserve(chartRef.value as HTMLDivElement)
  }
})
const hoverSeries = (name) => {
  getInstance()!.dispatchAction({
    type: 'highlight',
    // 可选，数据项名称，在有 dataIndex 的时候忽略
    name,
  })
}
const hoverCancel = (name) => {
  getInstance()!.dispatchAction({
    type: 'downplay',
    name,
  })
}

const toggleSeries = (name) => {
  getInstance()!.dispatchAction({
    type: 'legendToggleSelect',
    name,
  })
}
const getDomSize = () => {
  if (!chartRef.value) {
    return
  }
  chartWidth.value = chartRef.value.clientWidth
  chartHeight.value = chartRef.value.clientHeight
  setOptions(getChartOptions())
}

const calculatePagination = async () => {
  showPage.value = false
  currentPage.value = 1
  itemsPerPage.value = 0
  totalPages.value = 0
  if (scrollContent.value) {
    scrollContent.value.scrollTo({
      top: 0
    })
  }
  await nextTick()
  if (scrollContent.value) {
    const clientHeight = scrollContent.value.clientHeight
    const scrollHeight = scrollContent.value.scrollHeight
    if (scrollHeight > clientHeight) {
      showPage.value = true
      const num = Math.floor(clientHeight / itemHeight)
      itemsPerPage.value = num
      totalPages.value = Math.ceil(scrollHeight / (num * itemHeight))
    }

  }
}

const scroll = (direction) => {
  const scrollAmount = itemsPerPage.value * itemHeight
  currentPage.value += direction
  const top = direction * scrollAmount
  handleScroll(top)
}

const handleScroll = (top) => {
  if (scrollContent.value) {
    scrollContent.value.scrollBy({
      top,
      behavior: 'smooth'
    })
  }
}

const setData = () => {
  if (!props.chartData || !Array.isArray(props.chartData)) return
  const options = getChartOptions()
  setOptions(options)
}

watch(
  () => props.chartData,
  async (val) => {
    setChartColor()
    setData()
  },
  {
    immediate: true,
  },
)

</script>
<style scoped lang="scss">
.components-chart-box {
  display: flex;
  padding-top: 12px;

  .legend-box {
    display: flex;
    flex-direction: column;
    margin: 0 12px 12px 0;
    padding: 6px 12px;
    background: #F2F5F8;

    .legend-list {
      flex: 1;
      flex-shrink: 0;
      overflow: hidden;
      border-radius: 2px;


      li {
        display: flex;
        padding: 6px 0;
        color: var(--chart-text-color);
        font-size: 12px;
        line-height: 1;
        white-space: nowrap;
        cursor: pointer;

        .legend {
          display: inline-block;
          width: 12px;
          height: 12px;
          border-radius: 2px;
        }

        .value-box {
          display: flex;
          flex: 1;
          justify-content: space-between;
          margin-left: 4px;

          .value {
            color: #333;
          }
        }
      }
    }

    .op-box {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 12px;

      .ant-btn-link {
        color: #2f4554;
        font-size: 16px;

        &.is-disabled {
          color: #aaa;
        }
      }
    }
  }

  .chart-title {
    position: relative;
    top: 0;
    left: 0;
    flex: none;
    flex-shrink: 0;
    padding-left: 12px;

    &::before {
      left: 0;
    }
  }
}

.chart-container {
  display: flex;
  flex: 1;
  flex-direction: column;
  flex-shrink: 0;

  .chart {
    flex: 1;
    flex-shrink: 0;
    margin: 8px;
    overflow: hidden;
  }


}
</style>
